package eu.dominicum.ft.ui.web.jsf.view.bean;

import eu.dominicum.ft.pd.Country;
import eu.dominicum.ft.pd.EStageResultType;
import eu.dominicum.ft.pd.FantasyTourConfiguration;
import eu.dominicum.ft.pd.Location;
import eu.dominicum.ft.pd.StageResult;
import eu.dominicum.ft.pd.boundary.FantasyTourManagement;
import eu.dominicum.ft.pd.boundary.LocationManagement;
import eu.dominicum.ft.pd.mao.MakeStageResultDetailMAO;
import eu.dominicum.ft.pd.mao.MakeStageResultMAO;
import org.apache.myfaces.trinidad.context.RequestContext;

import javax.annotation.PostConstruct;
import javax.ejb.EJBException;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;

/**
 * Backing bean for the make-stage-result-dialog view.
 *
 * @author Harry Klerks
 * @since 2013M1
 */
@ManagedBean(name = "makeStageResultDialog")
@ViewScoped
public final class MakeStageResultDialogBean {

    /**
     * {@link FantasyTourManagement}.
     */
    @Inject
    private FantasyTourManagement fantasyTourManagement;

    /**
     * {@link LocationManagement}.
     */
    @Inject
    private LocationManagement locationManagement;

    /**
     * Stage result type select items.
     */
    private List<SelectItem> resultTypeItems;
    /**
     * Value of the selected result type.
     */
    private String selectedResultType;
    /**
     * The active configuration.
     */
    private FantasyTourConfiguration configuration;
    /**
     * Result detail count.
     */
    private Integer stageResultDetailCount = 0;
    /**
     * .
     */
    private List<MakeStageResultDetailMAO> stageResultDetails = new ArrayList<>();

    /**
     * .
     */
    @Inject
    private MakeStageResultMAO makeStageResultMAO;

    /**
     * Selected location.
     */
    private String selectedLocation;

    /**
     * Selected country.
     */
    private String selectedCountry;

    /**
     * List of Location select items.
     */
    private List<SelectItem> locationItems;

    /**
     * List of Country select items.
     */
    private List<SelectItem> countryItems;

    /**
     * Initialiser.
     */
    @PostConstruct
    public void init() {

        this.resultTypeItems = new ArrayList<>();
        for (EStageResultType stageResultType : EStageResultType.values()) {
            this.resultTypeItems.add(new SelectItem(stageResultType.name(),
                    stageResultType.getLabel()));
        }

        this.locationItems = new ArrayList<>();
        for (Location location : this.locationManagement.findAllLocations()) {
            this.locationItems.add(
                    new SelectItem(location.getId(),
                            location.getName() + " (" + location.getCountry().getCountryCode() + ")"));
        }

        this.countryItems = new ArrayList<>();
        for (Country country : this.locationManagement.findAllCountries()) {
            this.countryItems.add(new SelectItem(country.getId(), country.getName()));
        }

        this.configuration =
                (FantasyTourConfiguration) RequestContext.getCurrentInstance().getPageFlowScope().get("configuration");
    }

    /**
     * Event handler that fires when the result type is changed.
     *
     * @param valueChangeEvent -
     */
    public void onChangeResultType(
            final ValueChangeEvent valueChangeEvent) {

        String newValue = (String) valueChangeEvent.getNewValue();
        this.stageResultDetailCount = 0;
        if (EStageResultType.CLIMBING.name().equals(newValue)) {
            this.stageResultDetailCount = 3;
        }
        if (EStageResultType.POINTS.name().equals(newValue)) {
            this.stageResultDetailCount = 5;
        }
        if (EStageResultType.YOUTH.name().equals(newValue)) {
            this.stageResultDetailCount = this.configuration.getRidersInYouthResultCount();
        }
        if (EStageResultType.OVERALL.name().equals(newValue)) {
            this.stageResultDetailCount = this.configuration.getRiderInOverallResultCount();
        }
        this.resetDetailTableData(this.stageResultDetailCount);
    }

    /**
     * Rebuilds data for the detail table.
     *
     * @param detailCount -
     */
    private void resetDetailTableData(final Integer detailCount) {

        this.stageResultDetails = new ArrayList<>(detailCount);
        for (int idx = 1; idx <= detailCount; idx++) {
            MakeStageResultDetailMAO makeStageResultDetailMAO = new MakeStageResultDetailMAO();
            makeStageResultDetailMAO.setRank(idx);
            this.stageResultDetails.add(makeStageResultDetailMAO);
        }
    }

    /**
     * .
     *
     * @param newResultTypeItems -
     */
    public void setResultTypeItems(final List<SelectItem> newResultTypeItems) {
        this.resultTypeItems = newResultTypeItems;
    }

    /**
     * .
     *
     * @return List<SelectItem>
     */
    public List<SelectItem> getResultTypeItems() {
        return resultTypeItems;
    }

    /**
     * .
     *
     * @param newSelectedResultType -
     */
    public void setSelectedResultType(final String newSelectedResultType) {
        this.selectedResultType = newSelectedResultType;
    }

    /**
     * .
     *
     * @return String
     */
    public String getSelectedResultType() {
        return selectedResultType;
    }

    /**
     * Event handler that is fired when the 'Maken' button is clicked.
     *
     * @param actionEvent -
     */
    public void makeStageResult(final ActionEvent actionEvent) {

        try {
            Long fantasyTourId = (Long) RequestContext.getCurrentInstance().getPageFlowScope().get("fantasyTourId");
            Long stageId = Long.parseLong((String) RequestContext.getCurrentInstance().getPageFlowScope().get("stageId"));
            this.makeStageResultMAO.setFantasyTourId(fantasyTourId);
            this.makeStageResultMAO.setStageId(stageId);
            if (getSelectedResultType() != null) {
                this.makeStageResultMAO.setResultType(EStageResultType.valueOf(selectedResultType));
            }
            if (this.selectedLocation != null) {
                try {
                    this.makeStageResultMAO.setLocationId(Long.parseLong(this.selectedLocation));
                } catch (NumberFormatException nfex) {
                    this.makeStageResultMAO.setLocationId(null);
                }
            }
            if (this.selectedCountry != null) {
                try {
                    this.makeStageResultMAO.getMakeLocationMAO().setCountryId(Long.parseLong(this.selectedCountry));
                } catch (NumberFormatException nfex) {
                    this.makeStageResultMAO.getMakeLocationMAO().setCountryId(null);
                }
            }
            this.makeStageResultMAO.setMakeStageResultDetailsMAOs(this.stageResultDetails);
            StageResult stageResult = this.fantasyTourManagement.makeStageResult(this.makeStageResultMAO);
            RequestContext.getCurrentInstance().returnFromDialog(stageResult, null);
        } catch (EJBException eex) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    eex.getMessage(), null));
        }
    }

    /**
     * .
     *
     * @return FantasyTourConfiguration
     */
    public FantasyTourConfiguration getConfiguration() {
        return configuration;
    }

    /**
     * .
     *
     * @param newStageResultDetailCount -
     */
    public void setStageResultDetailCount(final Integer newStageResultDetailCount) {
        this.stageResultDetailCount = newStageResultDetailCount;
    }

    /**
     * .
     *
     * @return Integer
     */
    public Integer getStageResultDetailCount() {
        return stageResultDetailCount;
    }

    /**
     * .
     *
     * @param newStageResultDetails -
     */
    public void setStageResultDetails(final List<MakeStageResultDetailMAO> newStageResultDetails) {
        this.stageResultDetails = newStageResultDetails;
    }

    /**
     * .
     *
     * @return List<MakeStageResultDetailMAO>
     */
    public List<MakeStageResultDetailMAO> getStageResultDetails() {
        return stageResultDetails;
    }

    /**
     * .
     *
     * @return boolean
     */
    public boolean isPointsDetailRendered() {

        boolean rendered;
        if (EStageResultType.CLIMBING.name().equals(selectedResultType)
                || EStageResultType.POINTS.name().equals(selectedResultType)) {
            rendered = true;
        } else {
            rendered = false;
        }
        return rendered;
    }

    /**
     * Event handler that fires when the value of detail count changes.
     *
     * @param valueChangeEvent -
     */
    public void onChangeDetailCount(final ValueChangeEvent valueChangeEvent) {

        this.resetDetailTableData((Integer) valueChangeEvent.getNewValue());
    }

    /**
     * .
     *
     * @return MakeStageResultDetailMAO
     */
    public MakeStageResultMAO getMakeStageResultMAO() {
        return makeStageResultMAO;
    }

    /**
     * .
     *
     * @param newMakeStageResultMAO -
     */
    public void setMakeStageResultMAO(final MakeStageResultMAO newMakeStageResultMAO) {
        this.makeStageResultMAO = newMakeStageResultMAO;
    }

    /**
     * .
     *
     * @param newSelectedLocation -
     */
    public void setSelectedLocation(final String newSelectedLocation) {
        this.selectedLocation = newSelectedLocation;
    }

    /**
     * .
     *
     * @return String
     */
    public String getSelectedLocation() {
        return selectedLocation;
    }

    /**
     * .
     *
     * @param newSelectedCountry -
     */
    public void setSelectedCountry(final String newSelectedCountry) {
        this.selectedCountry = newSelectedCountry;
    }

    /**
     * .
     *
     * @return String
     */
    public String getSelectedCountry() {
        return selectedCountry;
    }

    /**
     * .
     *
     * @param newLocationItems -
     */
    public void setLocationItems(final List<SelectItem> newLocationItems) {
        this.locationItems = newLocationItems;
    }

    /**
     * .
     *
     * @return List<SelectItem>
     */
    public List<SelectItem> getLocationItems() {
        return locationItems;
    }

    /**
     * .
     *
     * @param newCountryItems -
     */
    public void setCountryItems(final List<SelectItem> newCountryItems) {
        this.countryItems = newCountryItems;
    }

    /**
     * .
     *
     * @return List<SelectItem>
     */
    public List<SelectItem> getCountryItems() {
        return countryItems;
    }
}
